#ifndef COLIST_H
#define COLIST_H

/*
*** WARNING *** CoList_SetItem does not increment the new item's reference
count, but does decrement the reference count of the item it replaces,
if not nil.  It does *decrement* the reference count if it is *not*
inserted in the list.  Similarly, CoList_GetItem does not increment the
returned item's reference count.
*/

/* l_item contains space for 'allocated' elements.  The number
 * currently in use is l_size.
 * Invariants:
 *     0 <= l_size <= l_allocated
 *     l_item == NULL implies l_size == l_allocated == 0
 *
 * Items must normally not be NULL, except during construction when
 * the list is not yet visible outside the function that builds it.
 */
typedef struct {
    COVALUE_HEAD
    ssize_t l_size;
    ssize_t l_allocated;
    CoValue **l_item;
} CoList;

extern CoType CoList_Type;

#define COLIST_CHECK(self)    CO_CHECK_TYPE(self, &CoList_Type)

CoValue *CoList_New(ssize_t size);
CoValue *CoList_GetItem(CoValue *self, ssize_t index);
int CoList_SetItem(CoValue *self, ssize_t index, CoValue *newitem);
int CoList_Append(CoValue *self, CoValue *newitem);
void CoList_SortItems(CoValue *self, int (*cmpfunc)(const void*, const void*));

#define CoList_GET_ITEM(self, i)  (((CoList *)(self))->l_item[i])
#define CoList_GET_SIZE(self)     (((CoList *)(self))->l_size)

#endif

